const express = require('express');
const router = express.Router();
const path = require('path');
const fs = require('fs');
const { ethers } = require('ethers');

const { createProvider, getContractArtifacts, getGasPriceForPolygon } = require('../utils/helpers');
const DatabaseService = require('../services/databaseService');

// Pause/Unpause token
router.post('/pause', async (req, res) => {
  try {
    const { tokenAddress, paused } = req.body;
    console.log(`🎯 Pause/Unpause request for token: ${tokenAddress}, paused: ${paused}`);
    if (!tokenAddress) throw new Error('Token address is required');
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    console.log(`🔍 Looking for Token artifacts at: ${tokenArtifactsPath}`);
    if (!fs.existsSync(tokenArtifactsPath)) {
      console.log(`❌ Token artifacts not found at: ${tokenArtifactsPath}`);
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    console.log(`✅ Token artifacts found at: ${tokenArtifactsPath}`);
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, wallet);
    console.log(`✅ Token contract instance created for ${tokenAddress}`);
    // Check if deployer is an agent
    const deployerAddress = await wallet.getAddress();
    const isAgent = await token.isAgent(deployerAddress);
    console.log(`🔍 Is deployer agent on token: ${isAgent}`);
    
    if (!isAgent) {
      throw new Error('Deployer is not an agent on this token');
    }
    
    // Get gas price for Polygon
    const gasPrice = await getGasPriceForPolygon(provider);
    const gasOptions = { gasPrice: gasPrice };
    
    // Pause or unpause the token
    const tx = paused ? await token.pause(gasOptions) : await token.unpause(gasOptions);
    console.log(`✅ Pause/Unpause transaction sent: ${tx.hash}`);
    await tx.wait();
    console.log(`✅ Pause/Unpause transaction confirmed`);
    
    res.json({
      success: true,
      message: `Token ${paused ? 'paused' : 'unpaused'} successfully`,
      tokenAddress: tokenAddress,
      paused: paused,
      transactionHash: tx.hash
    });
  } catch (error) {
    console.error('❌ Error in pause/unpause:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Get all tokens list
router.get('/list', async (req, res) => {
  try {
    console.log('🎯 Getting all tokens list');
    
    const tokensList = [];
    
    // 1. Get tokens from deployments.json
    try {
      const deploymentsPath = path.join(__dirname, '../../deployments.json');
      if (fs.existsSync(deploymentsPath)) {
        const deploymentsData = JSON.parse(fs.readFileSync(deploymentsPath, 'utf8'));
        
        // Handle new structure with easydeploy and advanced sections
        let deployments = [];
        if (deploymentsData.easydeploy) {
          deployments = deployments.concat(deploymentsData.easydeploy);
        }
        if (deploymentsData.advanced) {
          deployments = deployments.concat(deploymentsData.advanced);
        }
        
        console.log(`📋 Found ${deployments.length} deployments`);
        
        // Extract all tokens from deployments
        for (const deployment of deployments) {
          if (deployment.factory && deployment.tokens && deployment.tokens.length > 0) {
            for (const token of deployment.tokens) {
              if (token.token && token.token.address) {
                const tokenInfo = {
                  source: 'Deployment',
                  address: token.token.address,
                  name: token.token.name,
                  symbol: token.token.symbol,
                  deploymentId: token.deploymentId || deployment.deploymentId,
                  factory: deployment.factory.address,
                  timestamp: token.timestamp || deployment.timestamp,
                  suite: token.suite || deployment.suite
                };
                tokensList.push(tokenInfo);
              }
            }
          }
        }
      }
    } catch (deploymentError) {
      console.error('⚠️  Error reading deployments:', deploymentError.message);
    }
    
    // 2. Get tokens from database
    try {
      const dbTokens = await DatabaseService.getAllTokens();
      for (const dbToken of dbTokens) {
        // Check if token already exists in list
        const existingToken = tokensList.find(t => 
          t.address.toLowerCase() === dbToken.address.toLowerCase()
        );
        
        if (existingToken) {
          // Merge database info with existing token
          existingToken.decimals = dbToken.decimals;
          existingToken.totalSupply = dbToken.total_supply;
          existingToken.owner = dbToken.owner_address;
          existingToken.databaseId = dbToken.id;
          existingToken.createdAt = dbToken.created_at;
          existingToken.source = 'Both';
        } else {
          // Add token from database only
          tokensList.push({
            source: 'Database',
            address: dbToken.address,
            name: dbToken.name,
            symbol: dbToken.symbol,
            decimals: dbToken.decimals,
            totalSupply: dbToken.total_supply,
            owner: dbToken.owner_address,
            databaseId: dbToken.id,
            createdAt: dbToken.created_at
          });
        }
      }
    } catch (dbError) {
      console.error('⚠️  Error reading database:', dbError.message);
    }
    
    // 3. Try to get additional info from blockchain for tokens
    if (tokensList.length > 0) {
      try {
        const provider = createProvider();
        const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
        
        if (fs.existsSync(tokenArtifactsPath)) {
          const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
          
          // Get info for first 5 tokens to avoid timeout
          const tokensToCheck = tokensList.slice(0, 5);
          
          for (const token of tokensToCheck) {
            try {
              const contract = new ethers.Contract(token.address, tokenArtifacts.abi, provider);
              const [name, symbol, decimals, totalSupply, isPaused] = await Promise.all([
                contract.name().catch(() => token.name),
                contract.symbol().catch(() => token.symbol),
                contract.decimals().catch(() => token.decimals || 18),
                contract.totalSupply().catch(() => null),
                contract.paused ? contract.paused().catch(() => null) : Promise.resolve(null)
              ]);
              
              token.blockchainInfo = {
                name,
                symbol,
                decimals: typeof decimals === 'object' && decimals.toNumber ? decimals.toNumber() : Number(decimals),
                totalSupply: totalSupply ? ethers.utils.formatUnits(totalSupply, typeof decimals === 'object' && decimals.toNumber ? decimals.toNumber() : Number(decimals)) : null,
                isPaused
              };
            } catch (contractError) {
              console.log(`⚠️  Could not fetch blockchain info for ${token.address}:`, contractError.message);
            }
          }
        }
      } catch (blockchainError) {
        console.error('⚠️  Error fetching blockchain info:', blockchainError.message);
      }
    }
    
    console.log(`✅ Found ${tokensList.length} tokens total`);
    
    res.json({
      success: true,
      count: tokensList.length,
      tokens: tokensList
    });
  } catch (error) {
    console.error('❌ Error getting tokens list:', error);
    res.status(500).json({ 
      success: false, 
      error: error.message 
    });
  }
});

// Get token info
router.get('/token-info/:tokenAddress', async (req, res) => {
  try {
    const { tokenAddress } = req.params;
    console.log(`🎯 Getting token info for: ${tokenAddress}`);
    if (!tokenAddress) throw new Error('Token address is required');
    const provider = createProvider();
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    console.log(`🔍 Looking for Token artifacts at: ${tokenArtifactsPath}`);
    if (!fs.existsSync(tokenArtifactsPath)) {
      console.log(`❌ Token artifacts not found at: ${tokenArtifactsPath}`);
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    console.log(`✅ Token artifacts found at: ${tokenArtifactsPath}`);
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, provider);
    const [name, symbol, decimals, totalSupply, owner] = await Promise.all([
      token.name(),
      token.symbol(),
      token.decimals(),
      token.totalSupply(),
      token.owner()
    ]);
    
    // Handle BigNumber conversion properly
    const decimalsNumber = typeof decimals === 'object' && decimals.toNumber ? decimals.toNumber() : Number(decimals);
    
    const tokenInfo = {
      name,
      symbol,
      decimals: decimalsNumber,
      totalSupply: ethers.utils.formatUnits(totalSupply, decimalsNumber),
      owner,
      address: tokenAddress
    };
    
    console.log(`✅ Token info loaded: ${name} (${symbol})`);
    
    res.json({
      success: true,
      tokenInfo: tokenInfo
    });
  } catch (error) {
    console.error('❌ Error getting token info:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Get token status
router.get('/token-status/:tokenAddress', async (req, res) => {
  try {
    const { tokenAddress } = req.params;
    console.log(`🎯 Checking token status for: ${tokenAddress}`);
    if (!tokenAddress) throw new Error('Token address is required');
    const provider = createProvider();
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    console.log(`🔍 Looking for Token artifacts at: ${tokenArtifactsPath}`);
    if (!fs.existsSync(tokenArtifactsPath)) {
      console.log(`❌ Token artifacts not found at: ${tokenArtifactsPath}`);
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    console.log(`✅ Token artifacts found at: ${tokenArtifactsPath}`);
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, provider);
    
    // Check if the contract has the paused function
    const hasPausedFunction = tokenArtifacts.abi.some(item => 
      item.type === 'function' && item.name === 'paused'
    );
    
    if (!hasPausedFunction) {
      res.json({
        success: true,
        status: '⚠️ No pause function found',
        hasPauseFunction: false
      });
      return;
    }
    
    const isPaused = await token.paused();
    const status = isPaused ? '⏸️ PAUSED' : '▶️ ACTIVE';
    
    console.log(`✅ Token status: ${status}`);
    
    res.json({
      success: true,
      status: status,
      isPaused: isPaused,
      hasPauseFunction: true
    });
  } catch (error) {
    console.error('❌ Error checking token status:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Verify user
router.get('/verify-user/:tokenAddress/:userAddress', async (req, res) => {
  try {
    const { tokenAddress, userAddress } = req.params;
    console.log(`🎯 Checking verification for user: ${userAddress} on token: ${tokenAddress}`);
    
    if (!tokenAddress || !userAddress) {
      throw new Error('Token address and user address are required');
    }
    
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    
    // Get the Token contract
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    console.log(`🔍 Looking for Token artifacts at: ${tokenArtifactsPath}`);
    if (!fs.existsSync(tokenArtifactsPath)) {
      console.log(`❌ Token artifacts not found at: ${tokenArtifactsPath}`);
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    console.log(`✅ Token artifacts found at: ${tokenArtifactsPath}`);
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, wallet);
    console.log(`✅ Token contract instance created for ${tokenAddress}`);
    
    // Get the Identity Registry from the token
    const identityRegistryAddress = await token.identityRegistry();
    console.log(`🔍 Identity Registry: ${identityRegistryAddress}`);
    
    const irArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/IdentityRegistry.json');
    console.log(`🔍 Looking for IR artifacts at: ${irArtifactsPath}`);
    if (!fs.existsSync(irArtifactsPath)) {
      console.log(`❌ IdentityRegistry artifacts not found at: ${irArtifactsPath}`);
      throw new Error('IdentityRegistry artifacts not found. Please compile contracts first.');
    }
    console.log(`✅ IdentityRegistry artifacts found at: ${irArtifactsPath}`);
    const irArtifacts = JSON.parse(fs.readFileSync(irArtifactsPath, 'utf8'));
    const ir = new ethers.Contract(identityRegistryAddress, irArtifacts.abi, wallet);
    console.log(`✅ Identity Registry contract instance created for ${identityRegistryAddress}`);
    
    // Get user's OnchainID
    const onchainIdAddress = await ir.identity(userAddress);
    console.log(`🔍 User's OnchainID address: ${onchainIdAddress}`);
    
    if (onchainIdAddress === '0x0000000000000000000000000000000000000000') {
      res.json({
        success: true,
        verified: false,
        reason: 'User has no OnchainID registered',
        details: {
          userAddress: userAddress,
          onchainIdAddress: null,
          identityRegistry: identityRegistryAddress
        }
      });
      return;
    }
    
    // Check if user is verified
    const isVerified = await ir.isVerified(userAddress);
    console.log(`✅ Basic verification result: ${isVerified}`);
    
    // Get investor country
    const investorCountry = await ir.investorCountry(userAddress);
    console.log(`🔍 Investor country: ${investorCountry}`);
    
    // Get the TrustedIssuersRegistry
    const tirAddress = await ir.issuersRegistry();
    console.log(`🔍 TrustedIssuersRegistry: ${tirAddress}`);
    const tirArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/TrustedIssuersRegistry.json');
    console.log(`🔍 Looking for TIR artifacts at: ${tirArtifactsPath}`);
    if (!fs.existsSync(tirArtifactsPath)) {
      console.log(`❌ TrustedIssuersRegistry artifacts not found at: ${tirArtifactsPath}`);
      throw new Error('TrustedIssuersRegistry artifacts not found. Please compile contracts first.');
    }
    console.log(`✅ TrustedIssuersRegistry artifacts found at: ${tirArtifactsPath}`);
    const tirArtifacts = JSON.parse(fs.readFileSync(tirArtifactsPath, 'utf8'));
    const tir = new ethers.Contract(tirAddress, tirArtifacts.abi, wallet);
    console.log(`✅ TrustedIssuersRegistry contract instance created for ${tirAddress}`);
    
    // Get the ClaimTopicsRegistry
    const ctrAddress = await ir.topicsRegistry();
    console.log(`🔍 ClaimTopicsRegistry: ${ctrAddress}`);
    const ctrArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/ClaimTopicsRegistry.json');
    console.log(`🔍 Looking for CTR artifacts at: ${ctrArtifactsPath}`);
    if (!fs.existsSync(ctrArtifactsPath)) {
      console.log(`❌ ClaimTopicsRegistry artifacts not found at: ${ctrArtifactsPath}`);
      throw new Error('ClaimTopicsRegistry artifacts not found. Please compile contracts first.');
    }
    console.log(`✅ ClaimTopicsRegistry artifacts found at: ${ctrArtifactsPath}`);
    const ctrArtifacts = JSON.parse(fs.readFileSync(ctrArtifactsPath, 'utf8'));
    const ctr = new ethers.Contract(ctrAddress, ctrArtifacts.abi, wallet);
    console.log(`✅ ClaimTopicsRegistry contract instance created for ${ctrAddress}`);
    
    // Get required claim topics
    let requiredTopics = [];
    try {
      requiredTopics = await ctr.getClaimTopics();
      if (!Array.isArray(requiredTopics)) {
        requiredTopics = [];
      }
      console.log(`🔍 Required claim topics: ${requiredTopics.map(t => t.toString()).join(', ')}`);
    } catch (topicError) {
      console.log(`Warning: Could not get claim topics: ${topicError.message}`);
      requiredTopics = [];
    }
    
    // Load OnchainID artifacts
    const onchainIdArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Identity.json');
    console.log(`🔍 Looking for OnchainID artifacts at: ${onchainIdArtifactsPath}`);
    if (!fs.existsSync(onchainIdArtifactsPath)) {
      console.log(`❌ OnchainID artifacts not found at: ${onchainIdArtifactsPath}`);
      throw new Error('OnchainID artifacts not found. Please compile contracts first.');
    }
    console.log(`✅ OnchainID artifacts found at: ${onchainIdArtifactsPath}`);
    const onchainIdArtifacts = JSON.parse(fs.readFileSync(onchainIdArtifactsPath, 'utf8'));
    
    // Get the OnchainID contract
    const onchainId = new ethers.Contract(onchainIdAddress, onchainIdArtifacts.abi, wallet);
    console.log(`✅ OnchainID contract instance created for ${onchainIdAddress}`);
    
    // Check each required topic
    let verificationDetails = [];
    for (const topicId of requiredTopics) {
      let topicNum;
      try {
        topicNum = typeof topicId === 'object' && topicId.toNumber ? topicId.toNumber() : Number(topicId);
      } catch (numError) {
        console.log(`Warning: Could not convert topic ID ${topicId}: ${numError.message}`);
        continue;
      }
      
      console.log(`🔍 Checking topic ${topicNum}...`);
      
      // Get trusted issuers for this topic
      let trustedIssuers = [];
      let trustedIssuerAddresses = [];
      try {
        trustedIssuers = await tir.getTrustedIssuersForClaimTopic(topicNum);
        trustedIssuerAddresses = trustedIssuers.map(issuer => issuer.toString());
        console.log(`🔍 Found ${trustedIssuerAddresses.length} trusted issuers for topic ${topicNum}: ${trustedIssuerAddresses.join(', ')}`);
      } catch (issuerError) {
        console.log(`Warning: Could not get trusted issuers for topic ${topicNum}: ${issuerError.message}`);
      }
      
      // Check if user has claims for this topic
      let claims = [];
      try {
        claims = await onchainId.getClaimIdsByTopic(topicNum);
        console.log(`🔍 Found ${claims.length} claims for topic ${topicNum}`);
        if (!Array.isArray(claims)) {
          claims = [];
        }
      } catch (claimsError) {
        console.log(`Warning: Could not get claims for topic ${topicNum}: ${claimsError.message}`);
      }
      
      let hasValidClaim = false;
      let claimDetails = [];
      
      if (claims.length > 0) {
        // Check each claim
        for (const claimId of claims) {
          try {
            const claim = await onchainId.getClaim(claimId);
            const claimIssuer = claim.issuer;
            console.log(`🔍 Claim ${claimId} issuer: ${claimIssuer}, trusted issuers: ${trustedIssuerAddresses.join(', ')}`);
            
            // Check if the claim issuer is trusted for this topic
            if (trustedIssuerAddresses.map(addr => addr.toLowerCase()).includes(claimIssuer.toLowerCase())) {
              hasValidClaim = true;
              let claimData = '';
              try {
                claimData = ethers.utils.toUtf8String(claim.data);
              } catch (e) {
                claimData = claim.data; // Keep as hex if not UTF8
              }
              
              claimDetails.push({
                claimId: claimId.toString(),
                issuer: claimIssuer,
                data: claimData,
                scheme: claim.scheme.toNumber()
              });
              console.log(`🔍 Claim ${claimId} is valid! Data: ${claimData}`);
            } else {
              console.log(`🔍 Claim ${claimId} issuer ${claimIssuer} is not trusted for topic ${topicNum}`);
            }
          } catch (claimError) {
            console.log(`Warning: Could not get claim ${claimId}: ${claimError.message}`);
          }
        }
      }
      
      // If no claims found on OnchainID, check with ClaimIssuer contracts
      if (!hasValidClaim && trustedIssuerAddresses.length > 0) {
        console.log(`🔍 No claims found on OnchainID for topic ${topicNum}, checking ClaimIssuer contracts...`);
        
        for (const issuerAddress of trustedIssuerAddresses) {
          try {
            // Load ClaimIssuer artifacts
            const claimIssuerArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/ClaimIssuer.json');
            if (fs.existsSync(claimIssuerArtifactsPath)) {
              const claimIssuerArtifacts = JSON.parse(fs.readFileSync(claimIssuerArtifactsPath, 'utf8'));
              const claimIssuer = new ethers.Contract(issuerAddress, claimIssuerArtifacts.abi, wallet);
              
              // Try to validate a claim with this issuer
              // We need to create a signature for the claim data
              const claimData = ethers.utils.hexlify(ethers.utils.toUtf8Bytes("YES")); // Default claim value
              const dataHash = ethers.utils.keccak256(
                ethers.utils.defaultAbiCoder.encode(
                  ['address', 'uint256', 'bytes'],
                  [onchainIdAddress, topicNum, claimData]
                )
              );
              const signature = await wallet.signMessage(ethers.utils.arrayify(dataHash));
              
              const isValid = await claimIssuer.isClaimValid(onchainIdAddress, topicNum, signature, claimData);
              console.log(`🔍 ClaimIssuer ${issuerAddress} validation for topic ${topicNum}: ${isValid}`);
              
              if (isValid) {
                hasValidClaim = true;
                claimDetails.push({
                  claimId: 'ClaimIssuer-validated',
                  issuer: issuerAddress,
                  data: 'YES',
                  scheme: 1,
                  validatedBy: 'ClaimIssuer'
                });
                console.log(`🔍 Claim validated by ClaimIssuer ${issuerAddress} for topic ${topicNum}`);
                break; // Found a valid claim, no need to check other issuers
              }
            }
          } catch (issuerError) {
            console.log(`🔍 Error checking ClaimIssuer ${issuerAddress}: ${issuerError.message}`);
          }
        }
      }
      
      verificationDetails.push({
        topic: topicNum,
        required: true,
        hasClaims: claims.length > 0,
        hasValidClaim: hasValidClaim,
        trustedIssuers: trustedIssuerAddresses,
        claims: claimDetails,
        claimSource: claims.length > 0 ? 'OnchainID' : (hasValidClaim ? 'ClaimIssuer' : 'None')
      });
    }
    
    // Determine overall verification status
    const allTopicsVerified = verificationDetails.every(detail => detail.hasValidClaim);
    const verified = isVerified && allTopicsVerified;
    
    console.log(`✅ Verification check completed for user: ${userAddress}`);
    console.log(`📊 Overall verification status: ${verified} (Basic: ${isVerified}, Topics: ${allTopicsVerified})`);
    
    res.json({
      success: true,
      verified: verified,
      reason: verified ? 'User is fully verified' : 'User verification incomplete',
      details: {
        userAddress: userAddress,
        onchainIdAddress: onchainIdAddress,
        identityRegistry: identityRegistryAddress,
        isVerified: isVerified,
        investorCountry: typeof investorCountry === 'object' && investorCountry.toNumber ? investorCountry.toNumber() : Number(investorCountry),
        requiredTopics: requiredTopics.map(t => typeof t === 'object' && t.toNumber ? t.toNumber() : Number(t)),
        verificationDetails: verificationDetails
      }
    });
  } catch (error) {
    console.error('❌ Error in verify user:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Mint tokens
router.post('/mint', async (req, res) => {
  try {
    const { tokenAddress, amount, recipient } = req.body;
    console.log(`🎯 Minting ${amount} tokens to ${recipient} on token: ${tokenAddress}`);
    
    if (!tokenAddress || !amount || !recipient) {
      throw new Error('Token address, amount, and recipient are required');
    }
    
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    const deployerAddress = await wallet.getAddress();
    
    console.log(`🔍 Using deployer address: ${deployerAddress}`);
    
    // Get the Token contract
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    console.log(`🔍 Looking for Token artifacts at: ${tokenArtifactsPath}`);
    if (!fs.existsSync(tokenArtifactsPath)) {
      console.log(`❌ Token artifacts not found at: ${tokenArtifactsPath}`);
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    console.log(`✅ Token artifacts found at: ${tokenArtifactsPath}`);
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, wallet);
    console.log(`✅ Token contract instance created for ${tokenAddress}`);
    
    // Check if deployer is an agent
    const isAgent = await token.isAgent(deployerAddress);
    console.log(`🔍 Is deployer agent on token: ${isAgent}`);
    
    if (!isAgent) {
      throw new Error('Deployer is not an agent on this token');
    }
    
    // Convert amount to wei based on token decimals
    const amountInWei = ethers.utils.parseEther(amount);
    
    console.log(`🔍 Minting ${ethers.utils.formatEther(amountInWei)} tokens (${amountInWei} wei) to ${recipient}`);
    
    // Get gas price for Polygon
    const gasPrice = await getGasPriceForPolygon(provider);
    const gasOptions = { gasPrice: gasPrice };
    
    // Mint tokens
    const tx = await token.mint(recipient, amountInWei, gasOptions);
    console.log(`✅ Mint transaction sent: ${tx.hash}`);
    await tx.wait();
    console.log(`✅ Mint transaction confirmed`);
    // Balance check after mint
    const recipientBalance = await token.balanceOf(recipient);
    const recipientBalanceFormatted = ethers.utils.formatEther(recipientBalance);
    console.log(`🔍 Balance of ${recipient} after mint: ${recipientBalanceFormatted} tokens`);
    
    console.log(`✅ Successfully minted ${amount} tokens to ${recipient}`);
    
    res.json({
      success: true,
      message: `Successfully minted ${amount} tokens to ${recipient}`,
      tokenAddress: tokenAddress,
      amount: amount,
      recipient: recipient,
      transactionHash: tx.hash,
      recipientBalance: recipientBalanceFormatted
    });
    
  } catch (error) {
    console.error('❌ Error minting tokens:', error);
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

// Burn tokens
router.post('/burn', async (req, res) => {
  try {
    const { tokenAddress, amount, fromAddress } = req.body;
    console.log(`🎯 Burning ${amount} tokens from ${fromAddress} on token: ${tokenAddress}`);
    
    if (!tokenAddress || !amount || !fromAddress) {
      throw new Error('Token address, amount, and from address are required');
    }
    
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    const deployerAddress = await wallet.getAddress();
    
    console.log(`🔍 Using deployer address: ${deployerAddress}`);
    
    // Get the Token contract
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    console.log(`🔍 Looking for Token artifacts at: ${tokenArtifactsPath}`);
    if (!fs.existsSync(tokenArtifactsPath)) {
      console.log(`❌ Token artifacts not found at: ${tokenArtifactsPath}`);
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    console.log(`✅ Token artifacts found at: ${tokenArtifactsPath}`);
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, wallet);
    console.log(`✅ Token contract instance created for ${tokenAddress}`);
    
    // Check if deployer is an agent
    const isAgent = await token.isAgent(deployerAddress);
    console.log(`🔍 Is deployer agent on token: ${isAgent}`);
    
    if (!isAgent) {
      throw new Error('Deployer is not an agent on this token');
    }
    
    // Convert amount to wei based on token decimals (using parseEther as per mint)
    const amountInWei = ethers.utils.parseEther(amount);
    
    console.log(`🔍 Burning ${ethers.utils.formatEther(amountInWei)} tokens (${amountInWei} wei) from ${fromAddress}`);
    
    // Get gas price for Polygon
    const gasPrice = await getGasPriceForPolygon(provider);
    const gasOptions = { gasPrice: gasPrice };
    
    // Burn tokens
    const tx = await token.burn(fromAddress, amountInWei, gasOptions);
    console.log(`✅ Burn transaction sent: ${tx.hash}`);
    await tx.wait();
    console.log(`✅ Burn transaction confirmed`);
    // Balance check after burn
    const burnBalance = await token.balanceOf(fromAddress);
    const burnBalanceFormatted = ethers.utils.formatEther(burnBalance);
    console.log(`🔍 Balance of ${fromAddress} after burn: ${burnBalanceFormatted} tokens`);
    
    console.log(`✅ Successfully burned ${amount} tokens from ${fromAddress}`);
    
    res.json({
      success: true,
      message: `Successfully burned ${amount} tokens from ${fromAddress}`,
      tokenAddress: tokenAddress,
      amount: amount,
      fromAddress: fromAddress,
      transactionHash: tx.hash,
      fromAddressBalance: burnBalanceFormatted
    });
    
  } catch (error) {
    console.error('❌ Error burning tokens:', error);
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

// Transfer tokens (from signer to recipient)
router.post('/transfer', async (req, res) => {
  try {
    const { tokenAddress, amount, toAddress } = req.body;
    console.log(`🎯 Transferring ${amount} tokens to ${toAddress} on token: ${tokenAddress}`);
    
    if (!tokenAddress || !amount || !toAddress) {
      throw new Error('Token address, amount, and to address are required');
    }
    
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    const deployerAddress = await wallet.getAddress();
    
    console.log(`🔍 Using deployer address: ${deployerAddress}`);
    
    // Get the Token contract
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    console.log(`🔍 Looking for Token artifacts at: ${tokenArtifactsPath}`);
    if (!fs.existsSync(tokenArtifactsPath)) {
      console.log(`❌ Token artifacts not found at: ${tokenArtifactsPath}`);
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    console.log(`✅ Token artifacts found at: ${tokenArtifactsPath}`);
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, wallet);
    console.log(`✅ Token contract instance created for ${tokenAddress}`);
    
    // Convert amount to wei based on token decimals (using parseEther as per mint/burn)
    const amountInWei = ethers.utils.parseEther(amount);
    
    console.log(`🔍 Transferring ${ethers.utils.formatEther(amountInWei)} tokens (${amountInWei} wei) from ${deployerAddress} to ${toAddress}`);
    
    // Get gas price for Polygon
    const gasPrice = await getGasPriceForPolygon(provider);
    const gasOptions = { gasPrice: gasPrice };
    
    // Transfer tokens (from signer to recipient)
    const tx = await token.transfer(toAddress, amountInWei, gasOptions);
    console.log(`✅ Transfer transaction sent: ${tx.hash}`);
    const receipt = await tx.wait();
    console.log(`✅ Transfer transaction confirmed`);
    
    // Save transaction to database
    try {
      const transactionData = {
        tokenAddress,
        transactionHash: tx.hash,
        transactionType: 'transfer',
        fromAddress: deployerAddress,
        toAddress: toAddress,
        amount: amountInWei.toString(),
        usdtAmount: null,
        status: 'confirmed',
        blockNumber: receipt.blockNumber,
        gasUsed: receipt.gasUsed.toString()
      };
      
      await DatabaseService.saveTransaction(transactionData);
      console.log('✅ Transfer transaction saved to database');
    } catch (dbError) {
      console.error('⚠️ Failed to save transfer transaction to database:', dbError.message);
    }
    
    // Balance check after transfer
    const toBalance = await token.balanceOf(toAddress);
    const toBalanceFormatted = ethers.utils.formatEther(toBalance);
    console.log(`🔍 Balance of ${toAddress} after transfer: ${toBalanceFormatted} tokens`);
    
    console.log(`✅ Successfully transferred ${amount} tokens to ${toAddress}`);
    
    res.json({
      success: true,
      message: `Successfully transferred ${amount} tokens to ${toAddress}`,
      tokenAddress: tokenAddress,
      amount: amount,
      fromAddress: deployerAddress,
      toAddress: toAddress,
      transactionHash: tx.hash,
      toAddressBalance: toBalanceFormatted
    });
    
  } catch (error) {
    console.error('❌ Error transferring tokens:', error);
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

// TransferFrom (admin/agent flow): forcedTransfer from source to agent, then transfer to destination
router.post('/transfer-from', async (req, res) => {
  try {
    const { tokenAddress, fromAddress, toAddress, amount } = req.body;
    console.log(`🎯 TransferFrom request: ${amount} tokens from ${fromAddress} to ${toAddress} on token: ${tokenAddress}`);
    
    if (!tokenAddress || !fromAddress || !toAddress || !amount) {
      return res.status(400).json({ success: false, error: 'tokenAddress, fromAddress, toAddress, and amount are required' });
    }
    
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    const agentAddress = await wallet.getAddress();
    console.log(`🔍 Agent address: ${agentAddress}`);
    
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    if (!fs.existsSync(tokenArtifactsPath)) throw new Error('Token artifacts not found. Please compile contracts first.');
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, wallet);
    
    // Check if signer is an agent
    console.log(`🔍 Checking if ${agentAddress} is a token agent...`);
    const isAgent = await token.isAgent(agentAddress);
    console.log(`🔍 Is agent: ${isAgent}`);
    
    if (!isAgent) {
      throw new Error(`${agentAddress} is not a token agent. Add the agent to the token first.`);
    }
    
    // Get token decimals
    const amountBN = amount;
    
    // Check balances for all accounts
    const fromBalance = await token.balanceOf(fromAddress);
    const agentBalance = await token.balanceOf(agentAddress);
    const toBalance = await token.balanceOf(toAddress);
    
    console.log(`🔍 Balance check:`);
    console.log(`  From address (${fromAddress}): ${ethers.utils.formatEther(fromBalance)} tokens`);
    console.log(`  Agent (${agentAddress}): ${ethers.utils.formatEther(agentBalance)} tokens`);
    console.log(`  To address (${toAddress}): ${ethers.utils.formatEther(toBalance)} tokens`);
    console.log(`  Amount to transfer: ${ethers.utils.formatEther(amountBN)} tokens (${amountBN} wei)`);
    
    if (fromBalance.lt(amountBN)) {
      throw new Error(`Insufficient balance. Need ${amount} tokens, but ${fromAddress} only has ${ethers.utils.formatEther(fromBalance)}`);
    }
    
    // Get gas price for Polygon
    const gasPrice = await getGasPriceForPolygon(provider);
    const gasOptions = { gasPrice: gasPrice };
    
    console.log(`🔍 Step 1: forcedTransfer from ${fromAddress} to agent ${agentAddress}`);
    // Step 1: forcedTransfer from source to agent
    const tx1 = await token.forcedTransfer(fromAddress, agentAddress, amountBN, gasOptions);
    console.log(`✅ Step 1 transaction sent: ${tx1.hash}`);
    const receipt1 = await tx1.wait();
    console.log(`✅ Step 1 transaction confirmed`);
    
    // After Step 1
    const fromBalanceAfterStep1 = await token.balanceOf(fromAddress);
    const agentBalanceAfterStep1 = await token.balanceOf(agentAddress);
    const fromBalanceAfterStep1Formatted = ethers.utils.formatEther(fromBalanceAfterStep1);
    const agentBalanceAfterStep1Formatted = ethers.utils.formatEther(agentBalanceAfterStep1);
    console.log(`🔍 Balance after Step 1:`);
    console.log(`  From address: ${fromBalanceAfterStep1Formatted} tokens`);
    console.log(`  Agent: ${agentBalanceAfterStep1Formatted} tokens`);

    // Step 2
    const tx2 = await token.transfer(toAddress, amountBN, gasOptions);
    console.log(`✅ Step 2 transaction sent: ${tx2.hash}`);
    const receipt2 = await tx2.wait();
    console.log(`✅ Step 2 transaction confirmed`);
    
    // Save transfer-from transaction to database (Step 2 is the final transfer)
    try {
      const transactionData2 = {
        tokenAddress,
        transactionHash: tx2.hash,
        transactionType: 'transfer_from',
        fromAddress: agentAddress,
        toAddress: toAddress,
        amount: amountBN.toString(),
        usdtAmount: null,
        status: 'confirmed',
        blockNumber: receipt2.blockNumber,
        gasUsed: receipt2.gasUsed.toString()
      };
      
      await DatabaseService.saveTransaction(transactionData2);
      console.log('✅ TransferFrom transaction saved to database');
    } catch (dbError) {
      console.error('⚠️ Failed to save transfer-from to database:', dbError.message);
    }
    
    // Balance check after transfer-from
    const toBalanceAfter = await token.balanceOf(toAddress);
    const toBalanceAfterFormatted = ethers.utils.formatEther(toBalanceAfter);
    console.log(`🔍 Balance of ${toAddress} after transfer-from: ${toBalanceAfterFormatted} tokens`);

    console.log(`✅ TransferFrom completed successfully`);
    res.json({ 
      success: true, 
      transactionHash1: tx1.hash, 
      transactionHash2: tx2.hash,
      message: `Successfully transferred ${ethers.utils.formatEther(amountBN)} tokens from ${fromAddress} to ${toAddress} via agent`,
      balances: {
        fromAddressAfterStep1: fromBalanceAfterStep1Formatted,
        agentAfterStep1: agentBalanceAfterStep1Formatted,
        toAddressAfterStep2: toBalanceAfterFormatted
      }
    });
  } catch (error) {
    console.error('❌ Error in transfer-from:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Close token sale
router.post('/close-token', async (req, res) => {
  try {
    const { tokenAddress } = req.body;
    console.log(`🎯 Closing token sale for: ${tokenAddress}`);
    
    if (!tokenAddress) throw new Error('Token address is required');
    
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    const deployerAddress = await wallet.getAddress();
    
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    if (!fs.existsSync(tokenArtifactsPath)) {
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, wallet);
    
    // Check if deployer is an agent
    const isAgent = await token.isAgent(deployerAddress);
    if (!isAgent) {
      throw new Error('Deployer is not an agent on this token');
    }
    
    // Call closetoken function
    const tx = await token.closetoken();
    console.log(`✅ Close token transaction sent: ${tx.hash}`);
    await tx.wait();
    console.log(`✅ Close token transaction confirmed`);
    
    res.json({
      success: true,
      message: 'Token sale closed successfully',
      tokenAddress: tokenAddress,
      transactionHash: tx.hash
    });
  } catch (error) {
    console.error('❌ Error closing token:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Forced transfer
router.post('/forced-transfer', async (req, res) => {
  try {
    const { tokenAddress, fromAddress, toAddress, amount } = req.body;
    console.log(`🎯 Forced transfer: ${amount} tokens from ${fromAddress} to ${toAddress}`);
    
    if (!tokenAddress || !fromAddress || !toAddress || !amount) {
      throw new Error('Token address, from address, to address, and amount are required');
    }
    
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    const deployerAddress = await wallet.getAddress();
    
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    if (!fs.existsSync(tokenArtifactsPath)) {
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, wallet);
    
    // Check if deployer is an agent
    const isAgent = await token.isAgent(deployerAddress);
    if (!isAgent) {
      throw new Error('Deployer is not an agent on this token');
    }
    
    const amountInWei = ethers.utils.parseEther(amount);
    
    const tx = await token.forcedTransfer(fromAddress, toAddress, amountInWei);
    console.log(`✅ Forced transfer transaction sent: ${tx.hash}`);
    await tx.wait();
    console.log(`✅ Forced transfer transaction confirmed`);
    
    res.json({
      success: true,
      message: `Successfully forced transfer ${amount} tokens from ${fromAddress} to ${toAddress}`,
      tokenAddress: tokenAddress,
      fromAddress: fromAddress,
      toAddress: toAddress,
      amount: amount,
      transactionHash: tx.hash
    });
  } catch (error) {
    console.error('❌ Error in forced transfer:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Set address frozen
router.post('/set-address-frozen', async (req, res) => {
  try {
    const { tokenAddress, userAddress, freeze } = req.body;
    console.log(`🎯 Setting address frozen status: ${userAddress} = ${freeze}`);
    
    if (!tokenAddress || userAddress === undefined || freeze === undefined) {
      throw new Error('Token address, user address, and freeze status are required');
    }
    
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    const deployerAddress = await wallet.getAddress();
    
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    if (!fs.existsSync(tokenArtifactsPath)) {
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, wallet);
    
    // Check if deployer is an agent
    const isAgent = await token.isAgent(deployerAddress);
    if (!isAgent) {
      throw new Error('Deployer is not an agent on this token');
    }
    
    // Get gas price for Polygon
    const gasPrice = await getGasPriceForPolygon(provider);
    const gasOptions = { gasPrice: gasPrice };
    
    const tx = await token.setAddressFrozen(userAddress, freeze, gasOptions);
    console.log(`✅ Set address frozen transaction sent: ${tx.hash}`);
    await tx.wait();
    console.log(`✅ Set address frozen transaction confirmed`);
    
    res.json({
      success: true,
      message: `Successfully ${freeze ? 'frozen' : 'unfrozen'} address ${userAddress}`,
      tokenAddress: tokenAddress,
      userAddress: userAddress,
      freeze: freeze,
      transactionHash: tx.hash
    });
  } catch (error) {
    console.error('❌ Error setting address frozen:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Freeze partial tokens
router.post('/freeze-partial-tokens', async (req, res) => {
  try {
    const { tokenAddress, userAddress, amount } = req.body;
    console.log(`🎯 Freezing ${amount} tokens for ${userAddress}`);
    
    if (!tokenAddress || !userAddress || !amount) {
      throw new Error('Token address, user address, and amount are required');
    }
    
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    const deployerAddress = await wallet.getAddress();
    
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    if (!fs.existsSync(tokenArtifactsPath)) {
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, wallet);
    
    // Check if deployer is an agent
    const isAgent = await token.isAgent(deployerAddress);
    if (!isAgent) {
      throw new Error('Deployer is not an agent on this token');
    }
    
    const amountInWei = ethers.utils.parseEther(amount);
    
    const tx = await token.freezePartialTokens(userAddress, amountInWei);
    console.log(`✅ Freeze partial tokens transaction sent: ${tx.hash}`);
    await tx.wait();
    console.log(`✅ Freeze partial tokens transaction confirmed`);
    
    res.json({
      success: true,
      message: `Successfully froze ${amount} tokens for ${userAddress}`,
      tokenAddress: tokenAddress,
      userAddress: userAddress,
      amount: amount,
      transactionHash: tx.hash
    });
  } catch (error) {
    console.error('❌ Error freezing partial tokens:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Unfreeze partial tokens
router.post('/unfreeze-partial-tokens', async (req, res) => {
  try {
    const { tokenAddress, userAddress, amount } = req.body;
    console.log(`🎯 Unfreezing ${amount} tokens for ${userAddress}`);
    
    if (!tokenAddress || !userAddress || !amount) {
      throw new Error('Token address, user address, and amount are required');
    }
    
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    const deployerAddress = await wallet.getAddress();
    
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    if (!fs.existsSync(tokenArtifactsPath)) {
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, wallet);
    
    // Check if deployer is an agent
    const isAgent = await token.isAgent(deployerAddress);
    if (!isAgent) {
      throw new Error('Deployer is not an agent on this token');
    }
    
    const amountInWei = ethers.utils.parseEther(amount);
    
    const tx = await token.unfreezePartialTokens(userAddress, amountInWei);
    console.log(`✅ Unfreeze partial tokens transaction sent: ${tx.hash}`);
    await tx.wait();
    console.log(`✅ Unfreeze partial tokens transaction confirmed`);
    
    res.json({
      success: true,
      message: `Successfully unfroze ${amount} tokens for ${userAddress}`,
      tokenAddress: tokenAddress,
      userAddress: userAddress,
      amount: amount,
      transactionHash: tx.hash
    });
  } catch (error) {
    console.error('❌ Error unfreezing partial tokens:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Get balance
router.get('/balance/:tokenAddress/:userAddress', async (req, res) => {
  try {
    const { tokenAddress, userAddress } = req.params;
    console.log(`🎯 Getting balance for ${userAddress} on token: ${tokenAddress}`);
    
    if (!tokenAddress || !userAddress) {
      throw new Error('Token address and user address are required');
    }
    
    const provider = createProvider();
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    if (!fs.existsSync(tokenArtifactsPath)) {
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, provider);
    
    const balance = await token.balanceOf(userAddress);
    const balanceFormatted = ethers.utils.formatEther(balance);
    
    console.log(`✅ Balance for ${userAddress}: ${balanceFormatted} tokens`);
    
    res.json({
      success: true,
      balance: balanceFormatted,
      balanceRaw: balance.toString(),
      userAddress: userAddress,
      tokenAddress: tokenAddress
    });
  } catch (error) {
    console.error('❌ Error getting balance:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Get sale plan for token
router.get('/sale-plan/:tokenAddress', async (req, res) => {
  try {
    const { tokenAddress } = req.params;
    console.log(`🎯 Getting sale plan for token: ${tokenAddress}`);
    
    if (!tokenAddress) {
      throw new Error('Token address is required');
    }
    
    const provider = createProvider();
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    if (!fs.existsSync(tokenArtifactsPath)) {
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, provider);
    
    // Check if the contract has sale plan related functions
    const hasSalePlanFunction = tokenArtifacts.abi.some(item => 
      item.type === 'function' && item.name === 'getSalePlan'
    );
    
    if (!hasSalePlanFunction) {
      res.json({
        success: true,
        message: 'No sale plan function found on this token',
        hasSalePlan: false
      });
      return;
    }
    
    // Get sale plan details
    const salePlan = await token.getSalePlan();
    
    // Get USDT token address separately
    const usdtTokenAddress = await token.usdtToken();
    
    // Check if sale period has expired
    const currentTime = Math.floor(Date.now() / 1000);
    const endTime = Number(salePlan.startTime) + (Number(salePlan.validityPeriod) * 365 * 24 * 60 * 60);
    const isExpired = currentTime > endTime;
    
    const salePlanFormatted = {
      totalTokens: ethers.utils.formatEther(salePlan.totalTokens),
      price: ethers.utils.formatUnits(salePlan.price, 6), // Price is stored in USDT format (6 decimals)
      validityPeriod: salePlan.validityPeriod.toString(),
      dividendInterval: salePlan.dividendInterval.toString(),
      projectRev: salePlan.projectRev,
      platformRev: salePlan.platformRev,
      usdtToken: usdtTokenAddress,
      startTime: salePlan.startTime.toString(),
      endTime: endTime.toString(),
      isActive: salePlan.isActive,
      isExpired: isExpired,
      canTransfer: salePlan.isActive && !isExpired
    };
    console.log(`✅ Sale plan retrieved for token: ${tokenAddress}`);
    console.log(`📊 Sale plan status: isActive=${salePlan.isActive}, isExpired=${isExpired}, canTransfer=${salePlanFormatted.canTransfer}`);
    
    if (!salePlan.isActive || isExpired) {
      console.log(`⚠️  Sale plan is inactive or expired. Users cannot transfer tokens.`);
    }
    
    res.json({
      success: true,
      salePlan: salePlanFormatted,
      hasSalePlan: true
    });
  } catch (error) {
    console.error('❌ Error getting sale plan:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Set sale plan for token
router.post('/set-sale-plan', async (req, res) => {
  try {
    const { 
      tokenAddress, 
      totalTokens, 
      price, 
      validity, 
      dividendInterval, 
      projectRev, 
      platformRev, 
      usdtToken 
    } = req.body;
    
    console.log(`🎯 Setting sale plan for token: ${tokenAddress}`);
    
    if (!tokenAddress || !totalTokens || !price || !validity || !dividendInterval || !projectRev || !platformRev || !usdtToken) {
      throw new Error('Token address, total tokens, price, validity, dividend interval, project revenue, platform revenue, and USDT token are required');
    }
    
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    const deployerAddress = await wallet.getAddress();
    
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    if (!fs.existsSync(tokenArtifactsPath)) {
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, wallet);
    
    // Check if deployer is an agent
    const isAgent = await token.isAgent(deployerAddress);
    if (!isAgent) {
      throw new Error('Deployer is not an agent on this token');
    }
    
    // Convert values to appropriate formats
    const totalTokensBN = ethers.utils.parseEther(totalTokens);
    const priceBN = ethers.utils.parseUnits(price, 6); // Price should be stored in USDT format (6 decimals)
    const validityBN = ethers.BigNumber.from(validity);
    const dividendIntervalBN = ethers.BigNumber.from(dividendInterval);
    
    // Get gas price for Polygon
    const gasPrice = await getGasPriceForPolygon(provider);
    const gasOptions = { gasPrice: gasPrice };
    
    // Set sale plan
    const tx = await token.setSalePlan(
      totalTokensBN,
      priceBN,
      validityBN,
      dividendIntervalBN,
      projectRev,
      platformRev,
      usdtToken,
      gasOptions
    );
    
    console.log(`✅ Set sale plan transaction sent: ${tx.hash}`);
    const receipt = await tx.wait();
    console.log(`✅ Set sale plan transaction confirmed`);
    
    // 保存销售计划到数据库
    try {
      console.log('🔍 Attempting to save sale plan to database...');
      console.log('Token Address:', tokenAddress);
      
      // First, check if token exists in database
      const existingToken = await DatabaseService.getToken(tokenAddress);
      if (!existingToken) {
        console.error(`❌ Token ${tokenAddress} not found in database. Cannot save sale plan.`);
        console.log('💡 Suggestion: Redeploy the token to ensure it is saved to database first.');
      } else {
        console.log('✅ Token found in database:', existingToken.name, existingToken.symbol);
      }
      
      const salePlanData = {
        tokenAddress,
        totalTokens: totalTokensBN.toString(),
        price: priceBN.toString(),
        validityPeriod: validity,
        dividendInterval: dividendInterval,
        projectRev,
        platformRev,
        usdtToken,
        startTime: receipt.blockNumber.toString(),
        isActive: true
      };
      
      await DatabaseService.saveSalePlan(salePlanData);
      console.log('✅ Sale plan saved to database');
    } catch (dbError) {
      console.error('⚠️ Failed to save sale plan to database:', dbError.message);
      console.error('Full error:', dbError);
      // 不抛出错误，因为区块链操作已经成功
    }
    
    res.json({
      success: true,
      message: 'Sale plan set successfully',
      tokenAddress: tokenAddress,
      salePlan: {
        totalTokens: totalTokens,
        price: price,
        validity: validity,
        dividendInterval: dividendInterval,
        projectRev: projectRev,
        platformRev: platformRev,
        usdtToken: usdtToken
      },
      transactionHash: tx.hash
    });
  } catch (error) {
    console.error('❌ Error setting sale plan:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Purchase tokens
router.post('/purchase-tokens', async (req, res) => {
  try {
    const { tokenAddress, amount } = req.body;
    console.log(`🎯 Purchasing ${amount} tokens on token: ${tokenAddress}`);
    
    if (!tokenAddress || !amount) {
      throw new Error('Token address and amount are required');
    }
    
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    const deployerAddress = await wallet.getAddress();
    
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    if (!fs.existsSync(tokenArtifactsPath)) {
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, wallet);
    
    // Check if deployer is an agent
    const isAgent = await token.isAgent(deployerAddress);
    if (!isAgent) {
      throw new Error('Deployer is not an agent on this token');
    }
    
    // Get sale plan to check USDT token address and price
    const salePlan = await token.getSalePlan();
    const usdtTokenAddress = await token.usdtToken();
    
    // Get sale plan info for validation
    
    if (!usdtTokenAddress || usdtTokenAddress === '0x0000000000000000000000000000000000000000') {
      throw new Error('USDT token address not set in sale plan');
    }
    
    // Check USDT allowance
    const erc20AbiPath = path.join(__dirname, '../../trex-scaffold/packages/contracts/src/abis/erc20.json');
    const erc20Abi = JSON.parse(fs.readFileSync(erc20AbiPath, 'utf8'));
    const usdtContract = new ethers.Contract(usdtTokenAddress, erc20Abi, provider);
    
    const allowance = await usdtContract.allowance(deployerAddress, tokenAddress);
    const allowanceFormatted = ethers.utils.formatUnits(allowance, 6);
    console.log(`💰 USDT allowance: ${allowanceFormatted} USDT`);
    
    // Calculate required USDT amount
    // Convert amount to wei (18 decimals for tokens)
    const amountInWei = ethers.utils.parseEther(amount);
    
    console.log(`🔢 Amount in wei: ${amountInWei.toString()}`);
    console.log(`💰 Price in wei: ${salePlan.price.toString()}`);
    
    // Calculate USDT amount (amount is 18 decimals, price is 6 decimals)
    // Result is 24 decimals, contract divides by 1e18 to get 6 decimals
    const requiredUsdt24Decimals = amountInWei.mul(salePlan.price);
    console.log(`🧮 Required USDT (24 decimals): ${requiredUsdt24Decimals.toString()}`);
    
    // Contract divides by 1e18 to convert to 6 decimals (USDT format)
    const requiredUsdt6Decimals = requiredUsdt24Decimals.div(ethers.BigNumber.from(10).pow(18));
    console.log(`🧮 Required USDT (6 decimals): ${requiredUsdt6Decimals.toString()}`);
    
    // Convert to USDT format (6 decimals)
    const requiredUsdtFormatted = ethers.utils.formatUnits(requiredUsdt6Decimals, 6);
    console.log(`💸 Required USDT: ${requiredUsdtFormatted} USDT`);
    
    // Debug: Check if allowance is sufficient
    console.log(`🔍 Allowance check: ${allowance.toString()} >= ${requiredUsdt6Decimals.toString()} = ${allowance.gte(requiredUsdt6Decimals)}`);
    
    if (allowance.lt(requiredUsdt6Decimals)) {
      throw new Error(`Insufficient USDT allowance. Required: ${requiredUsdtFormatted} USDT, Available: ${allowanceFormatted} USDT`);
    }
    
    // Purchase tokens - convert amount to the format expected by the contract
    // The contract expects the amount in 18 decimals, but calculates USDT in 36 decimals
    // We need to pass the amount as is, since the contract handles the USDT calculation internally
    const tx = await token.purchaseTokens(amountInWei);
    
    console.log(`✅ Purchase tokens transaction sent: ${tx.hash}`);
    const receipt = await tx.wait();
    console.log(`✅ Purchase tokens transaction confirmed`);
    
    // Save transaction to database
    try {
      const transactionData = {
        tokenAddress,
        transactionHash: tx.hash,
        transactionType: 'purchase',
        fromAddress: deployerAddress,
        toAddress: deployerAddress,
        amount: amountInWei.toString(),
        usdtAmount: requiredUsdt6Decimals.toString(),
        status: 'confirmed',
        blockNumber: receipt.blockNumber,
        gasUsed: receipt.gasUsed.toString()
      };
      
      await DatabaseService.saveTransaction(transactionData);
      console.log('✅ Purchase transaction saved to database');
    } catch (dbError) {
      console.error('⚠️ Failed to save purchase transaction to database:', dbError.message);
    }
    
    // Get updated balance
    const buyerBalance = await token.balanceOf(deployerAddress);
    const buyerBalanceFormatted = ethers.utils.formatEther(buyerBalance);
    
    res.json({
      success: true,
      message: `Successfully purchased ${amount} tokens`,
      tokenAddress: tokenAddress,
      amount: amount,
      buyerAddress: deployerAddress,
      transactionHash: tx.hash,
      buyerBalance: buyerBalanceFormatted
    });
  } catch (error) {
    console.error('❌ Error purchasing tokens:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Approve USDT for token purchase
router.post('/approve-usdt', async (req, res) => {
  try {
    const { tokenAddress, usdtTokenAddress, amount } = req.body;
    console.log(`🔐 Approving ${amount} USDT for token: ${tokenAddress}`);
    
    if (!tokenAddress || !usdtTokenAddress || !amount) {
      throw new Error('Token address, USDT token address, and amount are required');
    }
    
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    const deployerAddress = await wallet.getAddress();
    
    // Load ERC20 ABI for USDT
    const erc20AbiPath = path.join(__dirname, '../../trex-scaffold/packages/contracts/src/abis/erc20.json');
    if (!fs.existsSync(erc20AbiPath)) {
      throw new Error('ERC20 ABI not found');
    }
    
    const erc20Abi = JSON.parse(fs.readFileSync(erc20AbiPath, 'utf8'));
    const usdtContract = new ethers.Contract(usdtTokenAddress, erc20Abi, wallet);
    
    // Convert amount to wei (assuming USDT has 6 decimals)
    const amountInWei = ethers.utils.parseUnits(amount, 6);
    
    // Approve USDT for token contract
    const tx = await usdtContract.approve(tokenAddress, amountInWei);
    
    console.log(`✅ USDT approval transaction sent: ${tx.hash}`);
    await tx.wait();
    console.log(`✅ USDT approval transaction confirmed`);
    
    // Check allowance
    const allowance = await usdtContract.allowance(deployerAddress, tokenAddress);
    const allowanceFormatted = ethers.utils.formatUnits(allowance, 6);
    
    res.json({
      success: true,
      message: `Successfully approved ${amount} USDT for token contract`,
      tokenAddress: tokenAddress,
      usdtTokenAddress: usdtTokenAddress,
      amount: amount,
      transactionHash: tx.hash,
      allowance: allowanceFormatted
    });
  } catch (error) {
    console.error('❌ Error approving USDT:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

// Set dividend
router.post('/set-dividend', async (req, res) => {
  try {
    const { tokenAddress, dividendRate, dividendToken } = req.body;
    console.log(`🎯 Setting dividend for token: ${tokenAddress}`);
    
    if (!tokenAddress || !dividendRate) {
      throw new Error('Token address and dividend rate are required');
    }
    
    const provider = createProvider();
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', provider);
    const deployerAddress = await wallet.getAddress();
    
    const tokenArtifactsPath = path.join(__dirname, '../../trex-scaffold/packages/react-app/src/contracts/Token.json');
    if (!fs.existsSync(tokenArtifactsPath)) {
      throw new Error('Token artifacts not found. Please compile contracts first.');
    }
    
    const tokenArtifacts = JSON.parse(fs.readFileSync(tokenArtifactsPath, 'utf8'));
    const token = new ethers.Contract(tokenAddress, tokenArtifacts.abi, wallet);
    
    // Check if deployer is an agent
    const isAgent = await token.isAgent(deployerAddress);
    if (!isAgent) {
      throw new Error('Deployer is not an agent on this token');
    }
    
    // Convert dividend rate to appropriate format (assuming it's a percentage with 2 decimals)
    const dividendRateBN = ethers.BigNumber.from(Math.floor(parseFloat(dividendRate) * 100));
    
    // Get gas price for Polygon
    const gasPrice = await getGasPriceForPolygon(provider);
    const gasOptions = { gasPrice: gasPrice };
    
    let tx;
    if (dividendToken) {
      // Set dividend with specific token
      tx = await token.setDividend(dividendRateBN, dividendToken, gasOptions);
    } else {
      // Set dividend with default token (ETH)
      tx = await token.setDividend(dividendRateBN, gasOptions);
    }
    
    console.log(`✅ Set dividend transaction sent: ${tx.hash}`);
    const receipt = await tx.wait();
    console.log(`✅ Set dividend transaction confirmed`);
    
    // Save dividend/public record to database
    try {
      const dividendData = {
        tokenAddress,
        roundNumber: 1, // You may need to track round numbers separately
        amount: dividendRate,
        dividendToken: dividendToken || 'ETH'
      };
      
      await DatabaseService.saveDividend(dividendData);
      console.log('✅ Dividend record saved to database');
    } catch (dbError) {
      console.error('⚠️ Failed to save dividend to database:', dbError.message);
    }
    
    res.json({
      success: true,
      message: 'Dividend set successfully',
      tokenAddress: tokenAddress,
      dividendRate: dividendRate,
      dividendToken: dividendToken || 'ETH',
      transactionHash: tx.hash
    });
  } catch (error) {
    console.error('❌ Error setting dividend:', error);
    res.status(500).json({ success: false, error: error.message });
  }
});

module.exports = router;